<template>
  <p class="tooltip" :style="style" ref="tooltipRef" @mouseenter.stop>
    {{ text }}
    <span class="tooltip-arrow" :style="arrowStyle"></span>
  </p>
</template>
<script setup lang="ts">
import { ref, getCurrentInstance, onMounted, onBeforeUnmount } from "vue";
defineProps<{ text?: string | number }>();
const tooltipRef = ref();
const style = ref({});
type arrowStyleProps = {
  bottom?: string;
  top?: string;
  left?: string;
  transform?: string;
};
const arrowStyle = ref<arrowStyleProps>({});
const parentNode = getCurrentInstance()?.parent?.refs.textRef as HTMLDivElement;
const handleMouseEnter = (e: MouseEvent) => {
  const {
    top, // 顶边距离视口顶部
    bottom: topToBottom, // 底边距离视口顶部
    left, // 左边距离视口左部
    right: rightToLeft, // 右边距离视口左部
    width: parentWidth, // 父元素的宽
    height: parentHeight, // 父元素的高
  } = (e.target as HTMLDivElement).getBoundingClientRect() || {}; // 父元素
  const bottom = window.innerHeight - topToBottom; // 底边距离视口底部
  const right = window.innerWidth - rightToLeft; // 右边距离视口右部
  const { height } = tooltipRef.value.getBoundingClientRect() || {}; // 当前元素
  const realWidth = Math.min(Math.round(parentWidth * 1.5), 576); // tooltip实际宽度，父元素的1.5倍
  const res = {
    width: realWidth + "px", // 宽是父元素的1.5倍
    right: window.innerWidth - rightToLeft + "px",
    top: top + "px",
    transform: "",
  };
  const arrowRes: arrowStyleProps = {};
  let translateX = "0";
  if (left < parentWidth * 0.25) {
    // 左侧超出视口
    translateX = `${-Math.round(left)}px`;
    arrowRes.left = `${Math.round(
      Math.max(Math.round(realWidth * 0.5 + left), 16)
    )}px`;
  } else if (right < parentWidth * 0.25) {
    // 右侧超出视口
    translateX = `${-Math.round(
      parentWidth * 0.25 + parentWidth * 0.25 - right
    )}px`;
    arrowRes.left = `${Math.min(
      Math.round(realWidth * 0.5 + (parentWidth * 0.25 - right)),
      realWidth - 16
    )}px`;
  } else {
    translateX = `${Math.round(-parentWidth * 0.25)}px`;
    arrowRes.left = `50%`;
  }
  if (top >= height || (bottom < height && top >= bottom)) {
    // 顶部没超出或者放底部会超出且顶部距离大于底部距离
    res.transform = `translate(${translateX}, -100%)`;
    arrowRes.bottom = "-7px";
  } else {
    res.transform = `translate(${translateX}, ${Math.round(parentHeight)}px)`;
    arrowRes.top = "-7px";
    arrowRes.transform = `translateX(-50%) rotate(180deg)`;
  }
  style.value = res;
  arrowStyle.value = arrowRes;
};
onMounted(() => {
  parentNode.addEventListener("mouseenter", handleMouseEnter);
});
onBeforeUnmount(() => {
  parentNode.removeEventListener("mouseenter", handleMouseEnter);
});
</script>
<style scoped lang="css">
.tooltip {
  opacity: 0;
  visibility: hidden;
  transition: opacity 0.3s;
  position: fixed;
  /* top: 0;
  left: 0; */
  /* transform: translateY(calc(-100% - 9px)); */
  max-width: 576px;
  min-width: 48px;
  padding: 8px 12px;
  color: #fff;
  text-align: left;
  text-decoration: none;
  word-wrap: break-word;
  background-color: rgba(65, 71, 94, 0.9);
  border-radius: 4px;
  box-shadow: none;
  z-index: 2;
}
.tooltip-arrow {
  display: block;
  content: "";
  position: absolute;
  /* bottom: -8px; */
  /* left: 50%; */
  height: 0;
  width: 0;
  transform: translateX(-50%);
  border: 8px solid transparent;
  border-top-color: rgba(65, 71, 94, 0.9);
  border-bottom: none;
}
</style>
